﻿using System;

using MathNet.Numerics.Distributions;

namespace Audit
{
    public class DistributionFacade
    {
        private DistributionsParameters _distributionsParameters;

        private Random random = new Random();

        private static readonly DistributionFacade DistributionFacadeInstance = new DistributionFacade();

        public static DistributionFacade Instance
        {
            get { return DistributionFacadeInstance; }
        }

        protected DistributionFacade() { }

        public void Init(DistributionsParameters parameters)
        {
            _distributionsParameters = parameters;
        }

        public int GetCountOfOrdersInDay()
        {
            var n = _distributionsParameters.Distributions[DistributionType.CountOfOrdersInDay].Parameters[0].Value;
            var p = _distributionsParameters.Distributions[DistributionType.CountOfOrdersInDay].Parameters[1].Value;

            return Binomial.Sample(random, p, (int)n);
        }

        public int GetCountOfChangedOrdersInDay()
        {
            var n = _distributionsParameters.Distributions[DistributionType.CountOfChangedOrdersInDay].Parameters[0].Value;
            var p = _distributionsParameters.Distributions[DistributionType.CountOfChangedOrdersInDay].Parameters[1].Value;

            return Binomial.Sample(random, p, (int)n);
        }

        public int GetCountOfPositions()
        {
            var n = _distributionsParameters.Distributions[DistributionType.CountOfPositions].Parameters[0].Value;
            var p = _distributionsParameters.Distributions[DistributionType.CountOfPositions].Parameters[1].Value;

            return Binomial.Sample(random, p, (int)n) + 1;
        }

        public int GetPosition()
        {
            var d = new Generators.DiscreteGenerator();

            d.InitGenerator(new[,] { { 6, 7, 8 },
            { 
                _distributionsParameters.Distributions[DistributionType.Position].Parameters[0].Value,
                _distributionsParameters.Distributions[DistributionType.Position].Parameters[1].Value,
                _distributionsParameters.Distributions[DistributionType.Position].Parameters[2].Value

            } });

            return (int)d.NextVariable();
        }

        public int GetCountOfProductsInPosition()
        {
            var n = _distributionsParameters.Distributions[DistributionType.CountOfProductsInPosition].Parameters[0].Value;
            var p = _distributionsParameters.Distributions[DistributionType.CountOfProductsInPosition].Parameters[1].Value;

            return Binomial.Sample(random, p, (int)n);
        }

        public int GetStatusOfOrder()
        {
            var d = new Generators.DiscreteGenerator();

            d.InitGenerator(new[,] { { 0, 1, 2 },
            { 
                _distributionsParameters.Distributions[DistributionType.StatusOfOrder].Parameters[0].Value,
                _distributionsParameters.Distributions[DistributionType.StatusOfOrder].Parameters[1].Value,
                _distributionsParameters.Distributions[DistributionType.StatusOfOrder].Parameters[2].Value

            } });

            return (int)d.NextVariable();
        }

        public int GetStatusOfChangeDeliveryMaterial()
        {
            var d = new Generators.DiscreteGenerator();
            d.InitGenerator(new[,] { { 0, 1 }, {
                _distributionsParameters.Distributions[DistributionType.StatusOfChangeDeliveryMaterial].Parameters[0].Value,
                _distributionsParameters.Distributions[DistributionType.StatusOfChangeDeliveryMaterial].Parameters[1].Value
            } });
            return (int)d.NextVariable();
        }

        public int GetDelayDeliveryMaterial()
        {
            var n = _distributionsParameters.Distributions[DistributionType.DelayDeliveryMaterial].Parameters[0].Value;
            var p = _distributionsParameters.Distributions[DistributionType.DelayDeliveryMaterial].Parameters[1].Value;

            return Binomial.Sample(random, p, (int)n);
        }

        public int GetCountOfDaysForModelling()
        {
            return (int)_distributionsParameters.Distributions[DistributionType.CountOfDaysForModelling].Parameters[0].Value;
        }
    }
}
